package com.hsy.sunflowerbao.base.ui.widget

import android.annotation.TargetApi
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.net.http.SslError
import android.os.Build
import android.os.Message
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.View
import android.webkit.ClientCertRequest
import android.webkit.ConsoleMessage
import android.webkit.GeolocationPermissions
import android.webkit.HttpAuthHandler
import android.webkit.JsPromptResult
import android.webkit.JsResult
import android.webkit.PermissionRequest
import android.webkit.SslErrorHandler
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient

/**
 * 自定义WebView
 * Created on 2018/1/2.
 *
 * @author Yang
 */
class BaseWebView : WebView {
    private var mClient = Client()

    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    private fun init() {

        settings.javaScriptEnabled = true
        settings.javaScriptCanOpenWindowsAutomatically = true
        settings.cacheMode = WebSettings.LOAD_NO_CACHE
        settings.setSupportZoom(true)
        settings.builtInZoomControls = true
        settings.useWideViewPort = true
        settings.loadWithOverviewMode = true
        settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN

        super.setWebChromeClient(MyWebChromeClient())
        super.setWebViewClient(MyWebViewClient())

        setClient(Client())
    }

    fun setClient(mClient: Client) {
        this.mClient = mClient
        try {
            val cls = Client::class.java.getDeclaredField("webView")
            cls.isAccessible = true
            cls.set(this.mClient, this)
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
            throw RuntimeException("Webview set failed.")
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
            throw RuntimeException("Webview set failed.")
        }

    }

    private inner class MyWebChromeClient : WebChromeClient() {
        override fun onProgressChanged(view: WebView, newProgress: Int) {
            mClient.onProgressChanged(this, view, newProgress)
        }

        override fun onReceivedTitle(view: WebView, title: String) {
            mClient.onReceivedTitle(this, view, title)
        }

        override fun onReceivedIcon(view: WebView, icon: Bitmap) {
            mClient.onReceivedIcon(this, view, icon)
        }

        override fun onReceivedTouchIconUrl(view: WebView, url: String, precomposed: Boolean) {
            mClient.onReceivedTouchIconUrl(this, view, url, precomposed)
        }

        override fun onShowCustomView(view: View, callback: WebChromeClient.CustomViewCallback) {
            mClient.onShowCustomView(this, view, callback)
        }

        override fun onHideCustomView() {
            mClient.onHideCustomView(this)
        }

        override fun onCreateWindow(view: WebView, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message): Boolean {
            return mClient.onCreateWindow(this, view, isDialog, isUserGesture, resultMsg)
        }

        override fun onRequestFocus(view: WebView) {
            mClient.onRequestFocus(this, view)
        }

        override fun onCloseWindow(window: WebView) {
            mClient.onCloseWindow(this, window)
        }

        override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean {
            return mClient.onJsAlert(this, view, url, message, result)
        }

        override fun onJsConfirm(view: WebView, url: String, message: String, result: JsResult): Boolean {
            return mClient.onJsConfirm(this, view, url, message, result)
        }

        override fun onJsPrompt(view: WebView, url: String, message: String, defaultValue: String, result: JsPromptResult): Boolean {
            return mClient.onJsPrompt(this, view, url, message, defaultValue, result)
        }

        override fun onJsBeforeUnload(view: WebView, url: String, message: String, result: JsResult): Boolean {
            return mClient.onJsBeforeUnload(this, view, url, message, result)
        }

        override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) {
            mClient.onGeolocationPermissionsShowPrompt(this, origin, callback)
        }

        override fun onGeolocationPermissionsHidePrompt() {
            mClient.onGeolocationPermissionsHidePrompt(this)
        }

        override fun onPermissionRequest(request: PermissionRequest) {
            mClient.onPermissionRequest(this, request)
        }

        override fun onPermissionRequestCanceled(request: PermissionRequest) {
            mClient.onPermissionRequestCanceled(this, request)
        }

        override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
            return mClient.onConsoleMessage(this, consoleMessage)
        }

        override fun getDefaultVideoPoster(): Bitmap? {
            val b = mClient.getDefaultVideoPoster(this)
            return b ?: super.getDefaultVideoPoster()
        }

        override fun getVideoLoadingProgressView(): View? {
            return mClient.getVideoLoadingProgressView(this)
        }

        override fun getVisitedHistory(callback: ValueCallback<Array<String>>) {
            mClient.getVisitedHistory(this, callback)
        }

        override fun onShowFileChooser(webView: WebView, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams): Boolean {
            return mClient.onShowFileChooser(this, webView, filePathCallback, fileChooserParams)
        }
    }

    private inner class MyWebViewClient : WebViewClient() {
        override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
            return mClient.shouldOverrideUrlLoading(this, view, url)
        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
            return mClient.shouldOverrideUrlLoading(this, view, request.url.toString())
        }

        override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
            mClient.onPageStarted(this, view, url, favicon)
        }

        override fun onPageFinished(view: WebView, url: String) {
            mClient.onPageFinished(this, view, url)
        }

        override fun onLoadResource(view: WebView, url: String) {
            mClient.onLoadResource(this, view, url)
        }

        override fun onPageCommitVisible(view: WebView, url: String) {
            mClient.onPageCommitVisible(this, view, url)
        }

        override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
            val res = mClient.shouldInterceptRequest(this, view, request)
            return res ?: super.shouldInterceptRequest(view, request)
        }

        override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
            mClient.onReceivedError(this, view, request, error)
        }

        override fun onReceivedHttpError(view: WebView, request: WebResourceRequest, errorResponse: WebResourceResponse) {
            mClient.onReceivedHttpError(this, view, request, errorResponse)
        }

        override fun onFormResubmission(view: WebView, dontResend: Message, resend: Message) {
            mClient.onFormResubmission(this, view, dontResend, resend)
        }

        override fun doUpdateVisitedHistory(view: WebView, url: String, isReload: Boolean) {
            mClient.doUpdateVisitedHistory(this, view, url, isReload)
        }

        override fun onReceivedSslError(view: WebView, shandler: SslErrorHandler, error: SslError) {
            mClient.onReceivedSslError(this, view, shandler, error)
        }

        override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) {
            mClient.onReceivedClientCertRequest(this, view, request)
        }

        override fun onReceivedHttpAuthRequest(view: WebView, shandler: HttpAuthHandler, host: String, realm: String) {
            mClient.onReceivedHttpAuthRequest(this, view, shandler, host, realm)
        }

        override fun shouldOverrideKeyEvent(view: WebView, event: KeyEvent): Boolean {
            return mClient.shouldOverrideKeyEvent(this, view, event)
        }

        override fun onUnhandledKeyEvent(view: WebView, event: KeyEvent) {
            mClient.onUnhandledKeyEvent(this, view, event)
        }

        override fun onScaleChanged(view: WebView, oldScale: Float, newScale: Float) {
            mClient.onScaleChanged(this, view, oldScale, newScale)
        }

        override fun onReceivedLoginRequest(view: WebView, realm: String, account: String, args: String) {
            mClient.onReceivedLoginRequest(this, view, realm, account, args)
        }
    }

    open class Client {
        val webView: BaseWebView? = null

        open fun dispatchKeyEvent(event: KeyEvent): Boolean {
            return false
        }

        open fun onProgressChanged(client: WebChromeClient, view: WebView, newProgress: Int) {

        }

        open fun onReceivedTitle(client: WebChromeClient, view: WebView, title: String) {

        }

        fun onReceivedIcon(client: WebChromeClient, view: WebView, icon: Bitmap) {

        }

        fun onReceivedTouchIconUrl(client: WebChromeClient, view: WebView, url: String, precomposed: Boolean) {

        }

        fun onShowCustomView(client: WebChromeClient, view: View, callback: WebChromeClient.CustomViewCallback) {

        }

        fun onHideCustomView(client: WebChromeClient) {

        }

        fun onCreateWindow(client: WebChromeClient, view: WebView, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message): Boolean {
            return false
        }

        fun onRequestFocus(client: WebChromeClient, view: WebView) {
            client.onRequestFocus(view)
        }

        fun onCloseWindow(client: WebChromeClient, window: WebView) {

        }

        fun onJsAlert(client: WebChromeClient, view: WebView, url: String, message: String, result: JsResult): Boolean {
            return false
        }

        fun onJsConfirm(client: WebChromeClient, view: WebView, url: String, message: String, result: JsResult): Boolean {
            return false
        }

        open fun onJsPrompt(client: WebChromeClient, view: WebView, url: String, message: String, defaultValue: String, result: JsPromptResult): Boolean {
            return false
        }

        fun onJsBeforeUnload(client: WebChromeClient, view: WebView, url: String, message: String, result: JsResult): Boolean {
            return false
        }

        fun onGeolocationPermissionsShowPrompt(client: WebChromeClient, origin: String, callback: GeolocationPermissions.Callback) {

        }

        fun onGeolocationPermissionsHidePrompt(client: WebChromeClient) {

        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        fun onPermissionRequest(client: WebChromeClient, request: PermissionRequest) {

        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        fun onPermissionRequestCanceled(client: WebChromeClient, request: PermissionRequest) {

        }

        fun onConsoleMessage(client: WebChromeClient, consoleMessage: ConsoleMessage): Boolean {
            return false
        }

        fun getDefaultVideoPoster(client: WebChromeClient): Bitmap? {
            return null
        }

        fun getVideoLoadingProgressView(client: WebChromeClient): View? {
            return null
        }

        fun getVisitedHistory(client: WebChromeClient, callback: ValueCallback<Array<String>>) {

        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        fun onShowFileChooser(client: WebChromeClient, webView: WebView, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams): Boolean {
            return false
        }

        open fun shouldOverrideUrlLoading(client: WebViewClient, view: WebView, url: String): Boolean {
            return false
        }

        fun onPageStarted(client: WebViewClient, view: WebView, url: String, favicon: Bitmap?) {

        }

        open fun onPageFinished(client: WebViewClient, view: WebView, url: String) {

        }

        fun onLoadResource(client: WebViewClient, view: WebView, url: String) {

        }

        @TargetApi(Build.VERSION_CODES.M)
        fun onPageCommitVisible(client: WebViewClient, view: WebView, url: String) {

        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        fun shouldInterceptRequest(client: WebViewClient, view: WebView, request: WebResourceRequest): WebResourceResponse? {
            return null
        }

        open fun onReceivedError(client: WebViewClient, view: WebView, request: WebResourceRequest, error: WebResourceError) {

        }

        @TargetApi(Build.VERSION_CODES.M)
        fun onReceivedHttpError(client: WebViewClient, view: WebView, request: WebResourceRequest, errorResponse: WebResourceResponse) {

        }

        fun onFormResubmission(client: WebViewClient, view: WebView, dontResend: Message, resend: Message) {

        }

        fun doUpdateVisitedHistory(client: WebViewClient, view: WebView, url: String, isReload: Boolean) {

        }

        fun onReceivedSslError(client: WebViewClient, view: WebView, handler: SslErrorHandler, error: SslError) {

        }

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        fun onReceivedClientCertRequest(client: WebViewClient, view: WebView, request: ClientCertRequest) {

        }

        fun onReceivedHttpAuthRequest(client: WebViewClient, view: WebView, handler: HttpAuthHandler, host: String, realm: String) {

        }

        fun shouldOverrideKeyEvent(client: WebViewClient, view: WebView, event: KeyEvent): Boolean {
            return false
        }

        fun onUnhandledKeyEvent(client: WebViewClient, view: WebView, event: KeyEvent) {

        }

        fun onScaleChanged(client: WebViewClient, view: WebView, oldScale: Float, newScale: Float) {

        }

        fun onReceivedLoginRequest(client: WebViewClient, view: WebView, realm: String, account: String, args: String) {

        }
    }
}